package com.fdq.dianping.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.fdq.dianping.entity.Result;
import com.fdq.dianping.entity.User;
import com.fdq.dianping.entity.dto.LoginFormDto;
import com.fdq.dianping.entity.dto.UserDto;
import com.fdq.dianping.service.UserService;
import com.fdq.dianping.service.impl.UserServiceImpl;
import com.fdq.dianping.util.Constants;
import com.fdq.dianping.util.JwtUtil;
import com.fdq.dianping.util.RegexUtils;
import com.fdq.dianping.util.ThreadLocalUtil;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author fdq
 * @since 2024-12-29
 */
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor        //自动把需要的属性用构造函数赋值，需要属性被final修饰
public class UserController {
    private final UserServiceImpl userService;
    //序列化器，把对象变成String序列保存在redis中
    @Resource       //AutoWeird注解是根据类型注入，Resource按类名注入
    private  StringRedisTemplate stringRedisTemplate;
    //对象序列化器
    @Resource
    private  RedisTemplate<String,Object> objectRedisTemplate;

    /*
    * 发送验证码
    * */
    @PostMapping("/senCode")
    public Result sendCode(String phone, HttpSession session){
        //1.校验手机号
        boolean phoneInvalid = RegexUtils.isPhoneInvalid(phone);
        if(phoneInvalid){
            return Result.error("手机号格式不正确！");
        }
        //2.生成验证码
        String code = RandomUtil.randomNumbers(6);
//        //3.验证码保存到session中
//        session.setAttribute("code", code);
        //验证码保存到redis,键为"code"+phone，值为验证码
        stringRedisTemplate.opsForValue().set(Constants.User_Code+phone,code,5, TimeUnit.MINUTES);
        //4.发送验证码
        System.out.println(code);
        return Result.success(code);
    }


    /*
    * 登录for测试
    * */
//    @PostMapping("/login")
//    public Result login(@RequestBody LoginFormDto loginFormDto , HttpSession session){
//        //1.校验手机号
//        boolean phoneInvalid = RegexUtils.isPhoneInvalid(loginFormDto.getPhone());
//        if(phoneInvalid){
//            return Result.error("手机号格式不正确！");
//        }
//
//        //2.校验验证码
//        String formDtoCode = loginFormDto.getCode();
//        String password = loginFormDto.getPassword();
//        //redis中的验证码数据
//        if(formDtoCode !=null){
//            String cacheCode = stringRedisTemplate.opsForValue().get(Constants.User_Code+loginFormDto.getPhone());
//            if(cacheCode == null || !cacheCode.equals(formDtoCode)){
//                return Result.error("验证码不正确！");
//            }
//        }else {
//            //密码登录
//            //3.根据手机号查询用户
//            User user = userService.query().eq("phone", loginFormDto.getPhone()).one();
//            if (!user.getPassword().equals(password)) {
//                return Result.error("密码错误");
//            }
//        }
//
//        //3.根据手机号查询用户
//        User user = userService.query().eq("phone", loginFormDto.getPhone()).one();
//        //4.用户为空自动注册
//        if(user == null){
//            user = userService.insertUserByPhone(loginFormDto.getPhone());
//            session.setAttribute(Constants.User,user);
//            return Result.success("登录成功！已为您注册用户！");
//        }
//
//        //5.把用户保存到redis
//        //用一个可视化的序列化器存储
//        UserDto userDto = BeanUtil.copyProperties(user,UserDto.class);
//
//        //为用户生成jwt令牌（token） ==>根据dto生成token,genToken方法参数是个map,所以先bean转map
//        Map<String,Object> claim = BeanUtil.beanToMap(userDto);
//        String token = JwtUtil.genToken(claim);
//
//        //存储
//        //键是"token"+token，值是对象dto
//        objectRedisTemplate.opsForValue().set(Constants.Token_Prefix+token,userDto);
//        //设置有效时间
//        objectRedisTemplate.expire(Constants.Token_Prefix+token,Constants.User_Token_TTL,TimeUnit.MINUTES);
//
//
//        return Result.success(token);
//    }

    /*
     * 登录
     * */
    @PostMapping("/login")
    public Result login(LoginFormDto loginFormDto , HttpSession session){
        //1.校验手机号
        boolean phoneInvalid = RegexUtils.isPhoneInvalid(loginFormDto.getPhone());
        if(phoneInvalid){
            return Result.error("手机号格式不正确！");
        }

        //2.校验验证码
        String formDtoCode = loginFormDto.getCode();
        String password = loginFormDto.getPassword();
        //redis中的验证码数据
        if(formDtoCode !=null){
            String cacheCode = stringRedisTemplate.opsForValue().get(Constants.User_Code+loginFormDto.getPhone());
            if(cacheCode == null || !cacheCode.equals(formDtoCode)){
                return Result.error("验证码不正确！");
            }
        }else {
            //密码登录
            //3.根据手机号查询用户
            User user = userService.query().eq("phone", loginFormDto.getPhone()).one();
            if (!user.getPassword().equals(password)) {
                return Result.error("密码错误");
            }
        }

        //3.根据手机号查询用户
        User user = userService.query().eq("phone", loginFormDto.getPhone()).one();
        //4.用户为空自动注册
        if(user == null){
            user = userService.insertUserByPhone(loginFormDto.getPhone());
            session.setAttribute(Constants.User,user);
            return Result.success("登录成功！已为您注册用户！");
        }

        //5.把用户保存到redis
        //用一个可视化的序列化器存储
        UserDto userDto = BeanUtil.copyProperties(user,UserDto.class);

        //为用户生成jwt令牌（token） ==>根据dto生成token,genToken方法参数是个map,所以先bean转map
        Map<String,Object> claim = BeanUtil.beanToMap(userDto);
        String token = JwtUtil.genToken(claim);

        //存储
        //键是"token"+token，值是对象dto
        objectRedisTemplate.opsForValue().set(Constants.Token_Prefix+token,userDto);
        //设置有效时间
        objectRedisTemplate.expire(Constants.Token_Prefix+token,Constants.User_Token_TTL,TimeUnit.MINUTES);


        return Result.success(token);
    }


    /*
    * 获取个人信息
    * */
    @GetMapping("/me")
    public Result me(){
        //获取当前登录用户信息
        Map<String,Object> userMap = ThreadLocalUtil.get();

        UserDto user = BeanUtil.mapToBean(userMap,UserDto.class,true);
        return Result.success(user);
    }

    /*
    * 修改个人信息
    * */
    @PostMapping("/update")
    public Result updateById(@RequestBody User user){
        boolean update = userService.updateById(user);
        if(update){
            return Result.success("个人信息修改成功");
        }else {
            return Result.error("个人信息修改失败");
        }
    }

    /*
    * 根据id获取用户
    * */
    @GetMapping("/getUserById")
    public Result getUserById(Long id){
        User user = userService.getById(id);
        UserDto userDto = BeanUtil.copyProperties(user, UserDto.class);
        return Result.success(userDto);
    }
}
